#ifndef WPGRAPHICSLIST_H
#define WPGRAPHICSLIST_H

#include <QGraphicsWidget>
#include <QGraphicsView>
#include <QList>

#include "busyindicator.h"
#include "themedatastorage.h"
#include "WPData.h"
#include "graphicslayoutiterator.h"

class QLabel;
class QVBoxLayout;
class QPropertyAnimation;

class PopupMenu;
class CommentsGraphicsView;
class WPGraphicsListItem;
class WPCommentGraphicsListItem;
class WPNetworkEngine;
class QGraphicsProxyWidget;
class QGraphicsLinearLayout;
class PannableView;
class BlogView;

class WPGraphicsList : public QGraphicsWidget
{
	Q_OBJECT
	
public slots:
	void setFocus(bool moveToCurrentItem = true);
	void ShowContextMenuForCurrent();
	
protected:
	WPGraphicsList(BlogView* aBlogView, const QGraphicsView& aGraphicsView,
	        PannableView* aPannableView);
	virtual ~WPGraphicsList();
	
	QGraphicsLinearLayout * AddLayout();
	void ClearLayout(QGraphicsLinearLayout & layout);
	
	static bool IsListItem(QGraphicsItem * item);
	
	struct SubLayout
    {
	    SubLayout(QGraphicsWidget * label, QGraphicsWidget * topShadow,
	            QGraphicsLayout * layout, QGraphicsWidget * bottomShadow)
	      : label(label), topShadow(topShadow), layout(layout), bottomShadow(bottomShadow) {}
	    
	    QGraphicsWidget * label;
	    QGraphicsWidget * topShadow;
	    QGraphicsLayout * layout;
	    QGraphicsWidget * bottomShadow;
    };
	typedef QList<QGraphicsLayoutItem *> LayoutItemList;
	
	void ShowSubLayout(SubLayout const & layout, QGraphicsLayoutItem * insertAfter);
	void ShowSubLayout(SubLayout const & layout, LayoutItemList const & insertAfterAlternatives);
	void HideSubLayout(SubLayout const & layout);
	
protected slots:
	void ShowContextMenu(WPGraphicsListItem* aItem);

    void MenuHiding();
    void ContextMenuHidden();

private:
    void resizeEvent(QGraphicsSceneResizeEvent* event);
    QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint) const;
    QPoint getMenuLocation(QPoint itemPoint);
    void keyPressEvent( QKeyEvent * event  );
	
private: // Functions to be overridden/implemented by deriving classes
    virtual void PopulatePopupMenuForCurrentItem(PopupMenu* aPopupMenu) = 0;
    virtual bool IsFocusable(QGraphicsLayoutItem * item)
        { return IsListItem(item->graphicsItem()); }
	
protected:
    // Create a scoped instance of this always when removing
    // QGraphicsItems from layouts. This will keep the iterator valid.
    class IteratorGuard {
    public:
        IteratorGuard(WPGraphicsList & list, QGraphicsItem * item);
        ~IteratorGuard();
    private:
        WPGraphicsList & list;
        bool decremented;
    };
    
    class FocusFunctor : public GraphicsLayoutIterator::FocusFunctor {
    public:
        FocusFunctor(WPGraphicsList & parent) : parent(parent) {}
        bool operator()(QGraphicsLayoutItem * item) { return parent.IsFocusable(item); }
    private:
        WPGraphicsList & parent;
    };
    
    FocusFunctor focusFunctor;
    
    WPGraphicsListItem * CurrentListItem();
    
	QGraphicsLinearLayout* iLayout;
	GraphicsLayoutIterator iCurrentItem;

	BusyIndicator& iBusyIndicator;
	ThemeData& iThemeData;
	
	// Whether or not to reposition to focused item
	// after hiding the context menu
	bool iRepositionAfterMenuHide;
	
private:
	const QGraphicsView&    iGraphicsView;
	
	PopupMenu* iPopupMenu;
	
	QPropertyAnimation* iAnimation;
	bool  iMenuHiding;

	PannableView* iPannableView;
};

#endif // WPGRAPHICSLIST_H
